#include "SudokuNakedSubsets.h"

SudokuNakedSubsets::SudokuNakedSubsets(QObject* parent) :
        SudokuAbstractSolvingTechnique("Naked Subsets", NakedSubsets, EliminateCandidate, parent)
{
}

int SudokuNakedSubsets::solve()
{
    for(int houseInd=0; houseInd<mSudokuData->getSize(); ++houseInd)
    {
        SudokuHouse rowCpy(*mSudokuData->houseAtRow(houseInd));
        rowCpy.sortByCandidatesAmount();
        findNakedSubsetsInHouse(&rowCpy);

        SudokuHouse colCpy(*mSudokuData->houseAtCol(houseInd));
        colCpy.sortByCandidatesAmount();
        findNakedSubsetsInHouse(&colCpy);

        SudokuHouse boxCpy(*mSudokuData->houseAtBox(houseInd));
        boxCpy.sortByCandidatesAmount();
        findNakedSubsetsInHouse(&boxCpy);
    }

    qDebug() << "SudokuNakedSubsets::solve: " << mCount;
    return mCount;
}


void SudokuNakedSubsets::findNakedSubsetsInHouse(SudokuHouse* house)
{
    int currentInd = mSudokuData->getSize()-1;
    //TODO change maxGroupSize to size/2 when hidden groups implemented
    //max group size is size-2
    //when we have complementary hidded, then ((size-2)/2)+1  ??
    int maxGroupSize = mSudokuData->getSize()-2;

    //skip filled cells and cells with candidate amound greater than size/2 (because there will be complementary hidden subset)
    while((!house->at(currentInd)->isEmpty() || house->at(currentInd)->countPossible()>maxGroupSize) && currentInd>0)
        --currentInd;

    while(currentInd>0 && house->at(currentInd)->countPossible()>=2)
    {
        SudokuCell* baseCell = house->at(currentInd);
        --currentInd;

        int currentGroupInd = currentInd;

        SudokuCellSet group;
        group.append(baseCell);

        while(currentGroupInd>=0 && group.size()+currentGroupInd+1>=baseCell->countPossible())//check if there is enought cells to collect group
        {
            if(house->at(currentGroupInd)->hasSameCandidatesOrLess(baseCell))
                group.append(house->at(currentGroupInd));
            --currentGroupInd;
        }

        if(group.size() == baseCell->countPossible())
        {
            //group found
            qDebug() << "group found: " << group << endl;
            mCount += house->eliminate(baseCell->getCandidateList(), NakedSubsets, group);

            //Locked Pair section
            if(group.size() <= mSudokuData->getSizeBox())
            {
                if(group.isCol() && !house->isCol())
                {
                    qDebug() << "Locked Pair/Group " << endl;
                    //TODO change solving method to Locked Pair?
                    SudokuHouse* house = mSudokuData->houseAtCol(group.at(0)->getCol());
                    mCount += house->eliminate(baseCell->getCandidateList(), NakedSubsets, group);
                }

                if(group.isRow() && !house->isRow())
                {
                    qDebug() << "Locked Pair/Group " << endl;
                    //TODO change solving method to Locked Pair?
                    SudokuHouse* house = mSudokuData->houseAtRow(group.at(0)->getRow());
                    mCount += house->eliminate(baseCell->getCandidateList(), NakedSubsets, group);
                }

                if(group.isBox() && !house->isBox())
                {
                    qDebug() << "Locked Pair/Group " << endl;
                    //TODO change solving method to Locked Pair?
                    SudokuHouse* house = mSudokuData->houseAtBox(group.at(0)->getBoxIndex());
                    mCount += house->eliminate(baseCell->getCandidateList(), NakedSubsets, group);
                }
            }
            //return here can cause worse efficency, because smaller groups could not be found
            //when there is big group without eliminated cadidates
            //TODO sort again?
        }
    }
}
